define([], function() {
  function addIndentChar(index, indent) {
    var ret = '';
    for (var i = 0; i < index; i++) {
      ret += indent;
    }
    return ret;
  }

  function formatText(text, indent, compress) {
    if (/^\s*$/.test(text)) {
      return '';
    }
    try {
      // "{ -> {
      text = text.replace(new RegExp('"{', 'gm'), '{');
      // }" -> }
      text = text.replace(new RegExp('}"', 'gm'), '}');
      // \" -> "
      text = text.replace(new RegExp('\\\\\\"', 'gm'), '"');
      // \\ r-> \r
      text = text.replace(new RegExp('\\\\\\\\r', 'gm'), '\\r');
      // \\n -> \n
      text = text.replace(new RegExp('\\\\\\\\n', 'gm'), '\\n');

      compress = compress || false;
      var draw = [];
      var line = '\n';
      var index = 0;
      var quoteCount = 0;
      var quoteOddEven = 0;
      var commentOddEven = 0;
      var current = '';
      var preChar = '';
      var nextChar = '';
      for (var i = 0; i < text.length; i++) {
        current = text.charAt(i);
        if (i + 1 < text.length) {
          nextChar = text.charAt(i + 1);
        }
        switch (current) {
        case '{':
        case '[':
          if (commentOddEven == 0) {
            if (preChar == '\"') {
              draw.push(current);
            } else if (quoteOddEven == 0) {
              draw.push(current);
              if (!compress) {
                index++;
                draw.push(line);
                draw.push(addIndentChar(index, indent));
              }
            } else {
              draw.push(current);
            }
          } else {
            draw.push(current);
          }
          break;
        case '/':
          if (quoteOddEven == 0) {
            if (nextChar == '*') {
              commentOddEven = 1;
              draw.push(current);
            } else if (preChar == '*') {
              commentOddEven = 0;
              draw.push(current);
              if (!compress) {
                draw.push(line);
                draw.push(addIndentChar(index, indent));
              }
            } else {
              draw.push(current);
            }
          } else {
            draw.push(current);
          }
          break;
        case '}':
        case ']':
          if (commentOddEven == 0) {
            if (nextChar == '\"') {
              draw.push(current);
            } else if (quoteOddEven == 0) {
              if (!compress) {
                index--;
                draw.push(line);
                draw.push(addIndentChar(index, indent));
              }
              draw.push(current);
            } else {
              draw.push(current);
            }
          } else {
            draw.push(current);
          }
          break;
        case ',':
          if (commentOddEven == 0) {
            if (quoteOddEven == 0/* && quoteCount > 0*/) {
              draw.push(current);
              if (!compress) {
                draw.push(line);
                draw.push(addIndentChar(index, indent));
              }
            } else {
              draw.push(current);
            }
          } else {
            draw.push(current);
          }
          break;
        case '\\':
          if (commentOddEven == 0) {
            if (i + 1 < text.length) {
              var next = text.charAt(i + 1);
              if (next == 't' || next == 'r' || next == 'n') {
                i++;
              }
            } else {
              draw.push(current);
            }
          } else {
            draw.push(current);
          }
          break;
        case ' ':
        case '\t':
        case '\r':
        case '\n':
          if (quoteOddEven != 0 || commentOddEven != 0) {
            draw.push(current);
          }
          break;
        case ':':
          if (commentOddEven == 0) {
            draw.push(current);
            if (quoteOddEven == 0) {
              if (!compress) {
                draw.push(' ');
              }
            }
          } else {
            draw.push(current);
          }
          break;
        case '\"':
          if (commentOddEven == 0) {
            quoteCount = quoteCount + 1;
            quoteOddEven = (quoteOddEven + 1) % 2;
            draw.push(current);
          } else {
            draw.push(current);
          }
          break;
        default:
          draw.push(current);
        }
        preChar = current;
      }

      return draw.join('');
    } catch (e) {
      console.error(e);
      return text;
    }
  }
  return {
    format: formatText,
    minify: function(text) {
      return formatText(text, '', true);
    }
  }
});
